package org.game.controll;

import org.game.map.GWField;
import org.game.map.GWMap;
import org.game.obj.GWObject;
import org.game.obj.building.GWBuilding;
import org.game.obj.building.GWCastle;
import org.game.obj.building.GWFarm;
import org.game.obj.building.GWForest;
import org.game.obj.building.GWIronOrePit;
import org.game.obj.unit.GWKnight;
import org.game.obj.unit.GWPeasant;
import org.game.obj.unit.GWSpearman;
import org.game.obj.unit.GWUnit;
import org.game.player.GWPlayer;

public abstract class GWPlayerController {
	
	private GWMap map;
	private GWPlayer player;
	
	public static final int PEASANT = 2;
	public static final int SPEARMAN = 4;
	public static final int KNIGHT = 8;
	
	public GWPlayerController(GWMap map, GWPlayer player) {
		this.map = map;
		this.player = player;
	}
	
	public abstract void createAction();
	
	public abstract void moveAction(int i);
	
	public abstract void gatherResourcesAction(int i);
	
	public abstract void bringResourcesAction(int i);
	
	public abstract void attackAction(int i);
	
	void addBuilding(GWBuilding obj) {

		if(player.canAdd(obj)) {
			if(map.canAdd(obj)) {	
				map.add(obj);
				player.add(obj);
			}
		}
	}
	
	void addUnit(GWUnit obj) {

		if(player.canAdd(obj)) {
			int x = player.getCastle().getX() + player.getCastle().getWidth()/2;
			int y = player.getCastle().getY() + player.getCastle().getHeight();
			obj.setX(x);
			obj.setY(y);
			if(map.canAdd(obj)) {	
				map.add(obj);
				player.add(obj);
			}
		}
	}
	
	void releaseUnits() {
		for(int i = 0; i < GWPlayer.UNIT_LIMIT; i++) {
			GWUnit unit = player.getUnit(i);
			if(unit != null) {
				unit.setBusy(false);
				if(unit.isDead()) {
					map.getField(unit.getX(), unit.getY()).setObject(null);
					player.setUnit(i, null);
				}
			}
		}
	}
	
	public final void addUnit(int type) {
		GWUnit obj = null;
		switch(type) {
		case PEASANT:
			obj = new GWPeasant();
			break;
		case SPEARMAN:
			obj = new GWSpearman();
			break;
		case KNIGHT:
			obj = new GWKnight();
			break;
		}
		addUnit(obj);
	}
	
	public final void moveUnit(int unitNumber, int mode) {
		GWUnit unit = player.getUnit(unitNumber);
		if(unit.isBusy()) return;
		
		int oldx = unit.getX();
		int oldy = unit.getY();
		int[] p = nextField(oldx, oldy, mode);
		int x = p[0];
		int y = p[1];
		
		if(map.getField(x, y) != null && map.getField(x, y).isFree()) {
			unit.setX(x);
			unit.setY(y);
			map.getField(oldx, oldy).setObject(null);
			map.getField(x, y).setObject(unit);
			unit.setBusy(true);
		}
	}
	
	public final void gatherResources(int unitNumber, int mode) {
		GWUnit unit = player.getUnit(unitNumber);
		if(unit.isBusy()) return;
		
		if(unit instanceof GWPeasant) {
			int[] p = nextField(unit.getX(), unit.getY(), mode);
			int x = p[0];
			int y = p[1];
			GWField field = map.getField(x, y);
			if(field == null) return;
			GWObject obj = field.getObject();
			if(obj == null) return;
			if(obj instanceof GWFarm) {
				((GWPeasant) unit).gatherResources(GWPeasant.FOOD);
				unit.setBusy(true);
				return;
			}
			if(obj instanceof GWForest) {
				((GWPeasant) unit).gatherResources(GWPeasant.WOOD);			
				unit.setBusy(true);
				return;
			}
			if(obj instanceof GWIronOrePit) {
				((GWPeasant) unit).gatherResources(GWPeasant.IRON_ORE);
				unit.setBusy(true);
				return;
			}
		}
	}
	
	public final void bringResources(int unitNumber, int mode) {
		GWUnit unit = player.getUnit(unitNumber);
		if(unit.isBusy()) return;
		
		if(unit instanceof GWPeasant) {
			int[] p = nextField(unit.getX(), unit.getY(), mode);
			int x = p[0];
			int y = p[1];
			GWField field = map.getField(x, y);
			if(field == null) return;
			GWObject obj = field.getObject();
			if(obj == null) return;
			if(obj instanceof GWCastle && obj.getPlayer() == player.getPlayer()) {
				int type = ((GWPeasant) unit).bringResources();
				player.addResources(type);
				unit.setBusy(true);
				return;
			}
		}
	}
	
	public final void attackEnemy(int unitNumber, int mode) {
		GWUnit unit = player.getUnit(unitNumber);
		if(unit.isBusy()) return;
		
		int[] p = nextField(unit.getX(), unit.getY(), mode);
		int x = p[0];
		int y = p[1];
		GWField field = map.getField(x, y);
		if(field == null) return;
		GWObject obj = field.getObject();
		if(obj == null) return;
		if(obj instanceof GWUnit || obj instanceof GWBuilding) { 
			if(obj.getPlayer() != unit.getPlayer() &&
					obj.getPlayer() != 0 && !obj.isDead()) {
				int dmg = unit.getDamage();
				obj.damage(dmg);
				if(obj.isDead()) player.setKills(player.getKills() + 1);
				unit.setBusy(true);
			}
		}
	}
	
	public GWMap getMap() {
		return new GWMap(map);
	}
	
	public GWPlayer getPlayer() {
		return new GWPlayer(player);
	}
	
	private int[] nextField(int x, int y, int mode) {
		int[] p = new int[2];
		
		switch(mode) {
		case 7:
			x--;
			y++;
			break;
		case 8:
			y++;
			break;
		case 9:
			x++;
			y++;
			break;
		case 4:
			x--;
			break;
		case 6:
			x++;
			break;
		case 1:
			x--;
			y--;
			break;
		case 2:
			y--;
			break;
		case 3:
			x++;
			y--;
			break;
		}
		p[0] = x;
		p[1] = y;
		return p;
	}
}
